/**
  Copyright (c) [2024] [JiangNan]
  [simple-go-test] is licensed under Mulan PSL v2.
  You can use this software according to the terms and conditions of the Mulan PSL v2.
  You may obtain a copy of Mulan PSL v2 at:
           http://license.coscl.org.cn/MulanPSL2
  THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
  See the Mulan PSL v2 for more details.
*/

package progressbar

import (
	"fmt"
	"gitee.com/jn-qq/go-tools/data"
	"runtime"
	"strconv"
	"strings"
	"time"
)

type Bar struct {
	prefix     string
	suffix     Ends
	total      int
	current    int
	graph      string
	graphTotal int
	backGraph  string
	color      int
	start      int64
}

type Ends struct {
	costTime   bool
	percentage bool
	rate       bool
}

// NewBar 创建进度条对象
//
//	prefix 进度条前缀
//	total 进度条总数据大小
//	graph 进度条字符样式
func NewBar(prefix string, total int, graph string) *Bar {
	if prefix == "" {
		prefix = "Running"
	}
	if total <= 0 {
		panic("total must be greater than zero")
	}
	if graph == "" {
		graph = "█"
	}
	return &Bar{
		prefix:     prefix,
		suffix:     Ends{costTime: true, percentage: true, rate: true},
		total:      total,
		current:    0,
		graphTotal: 50,
		graph:      graph,
		backGraph:  " ",
		color:      32,
		start:      time.Now().Unix(),
	}
}

// SetSuffix 设置后缀是否展示，默认全展示
//
//	costTime 用时
//	percentage 百分比
//	rate 分数比
func (bar *Bar) SetSuffix(costTime, percentage, rate bool) {
	bar.suffix = Ends{costTime, percentage, rate}
}

// PrintProgress 打印进度
func (bar *Bar) PrintProgress(p int) {
	bar.current = p
	printStr := "\r" + bar.prefix
	printStr += " [" + strings.Replace(bar.backString(), bar.backGraph, bar.graph, bar.currentGraphNumber()) + "] "
	if bar.suffix.rate {
		Len := len(strconv.Itoa(bar.total)) - len(strconv.Itoa(bar.current))
		printStr += fmt.Sprintf("%s%d/%d", strings.Repeat(" ", Len), bar.current, bar.total)
	}
	if bar.suffix.percentage {
		printStr += fmt.Sprintf(" %.2f%%", float64(bar.current)/float64(bar.total)*100)
	}
	if bar.suffix.costTime {
		printStr += " " + data.NewSecond(time.Now().Unix()-bar.start).String()
	}
	if runtime.GOOS == "linux" {
		printStr = fmt.Sprintf(" %c[%vm%v%c[0m", 0x1B, bar.color, printStr, 0x1B)
	}
	fmt.Print(printStr)
}

func (bar *Bar) SetGraphTotal(total int) {
	bar.graphTotal = total
}

func (bar *Bar) backString() string {
	back := ""
	for i := 0; i < bar.graphTotal; i++ {
		back += bar.backGraph
	}
	return back
}

func (bar *Bar) currentGraphNumber() int {
	return int(float64(bar.graphTotal) * (float64(bar.current) / float64(bar.total)))
}
